package JLog;

import java.io.FileWriter;
import java.io.PrintWriter;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.Date;
import jmysql.classMySQL;

/**
 *
 * @author cmerino
 * @version 1.0
 * 
 */
public class ClassMensaje {

    /***                     ATRIBUTOS PÚBLICOS                        ***/
    /***                     ATRIBUTOS PRIVADOS                        ***/
    private int __CODE_TYPE_STR_LOG;
    private Timestamp __INSTANTE;
    private String __TYPE;
    private String __TIME;
    private String __SQL_TIME;
    private long __LONG_TIME;
    private String __MENSAJE;
    private String __METHOD;
    private String __USUARIO;
    private String __AMBIENTE;
    private int __ID_APLICACION;
    private String __PROPERTIE_URL = "src\\DATA_LAYER\\SQL\\propSQL.properties";

    /*********************************************************************/
    /***                       MÉTODOS PÚBLICOS                        ***/
    /*********************************************************************/
    /**
     * 
     * Constructor de la Clase <b>classMensaje</b>.
     * Define el Code Type (<code>__CODE_TYPE_STR_LOG</code>) como 1
     * 
     * @param __STR_TYPE Define el tipo de mensaje que se registrará en el log
     * @param __STR_MENSAJE Define el mensaje que será registrado en el log.
     * 
     */
    public ClassMensaje(
            String __STR_TYPE,
            String __STR_MENSAJE) {
        this.__CODE_TYPE_STR_LOG = 1;
        setObjClassMensaje(__STR_TYPE, __STR_MENSAJE);
    }   /* FIN public classMensaje */


    /**
     * 
     * Constructor de la Clase <b>classMensaje</b>.
     * * Define el Code Type (<code>__CODE_TYPE_STR_LOG</code>) como 2
     * 
     * @param __STR_TYPE Define el tipo de mensaje que se registrará en el log
     * @param __STR_MENSAJE Define el mensaje que será registrado en el log.
     * @param __METHOD Define el método al cual se asocia el evento de log.
     * 
     */
    public ClassMensaje(
            String __STR_TYPE,
            String __STR_MENSAJE,
            String __METHOD) {
        this.__CODE_TYPE_STR_LOG = 2;
        setObjClassMensaje(__STR_TYPE, __STR_MENSAJE, __METHOD);
    }   /* FIN public classMensaje */


    /**
     * 
     * Constructor de la Clase <b>classMensaje</b>.
     * Define el Code Type (<code>__CODE_TYPE_STR_LOG</code>) como 3
     * 
     * @param __STR_TYPE Define el tipo de mensaje que se registrará en el log
     * @param __STR_MENSAJE Define el mensaje que será registrado en el log.
     * @param __METHOD Define el método al cual se asocia el evento de log.
     * @param __USUARIO Define el usuario generador del evento log (es útil 
     *                  para el control de sistemas multiusuarios).
     * 
     */
    public ClassMensaje(
            String __STR_TYPE,
            String __STR_MENSAJE,
            String __METHOD,
            String __USUARIO) {
        this.__CODE_TYPE_STR_LOG = 3;
        setObjClassMensaje(__STR_TYPE, __STR_MENSAJE, __METHOD, __USUARIO);
    }   /* FIN public classMensaje */


    /**
     * 
     * Constructor de la Clase <b>classMensaje</b>.
     * Define el Code Type (<code>__CODE_TYPE_STR_LOG</code>) como 4
     * 
     * @param __STR_TYPE Define el tipo de mensaje que se registrará en el log
     * @param __STR_MENSAJE Define el mensaje que será registrado en el log.
     * @param __METHOD Define el método al cual se asocia el evento de log.
     * @param __USUARIO Define el usuario generador del evento log (es útil 
     *                  para el control de sistemas multiusuarios).
     * @param __AMBIENTE Define el ambiente en que es generado el evento log 
     *                   (es útil para implementaciones de sistemas 
     *                   multiambiente).
     * 
     */
    public ClassMensaje(
            String __STR_TYPE,
            String __STR_MENSAJE,
            String __METHOD,
            String __USUARIO,
            String __AMBIENTE) {
        this.__CODE_TYPE_STR_LOG = 4;
        setObjClassMensaje(
                __STR_TYPE,
                __STR_MENSAJE,
                __METHOD,
                __USUARIO,
                __AMBIENTE);
    }   /* FIN public classMensaje */


    /**
     * 
     * Método que tiene como tarea escribir el registro del evento log en un 
     * archivo.
     * 
     * @param strArchivo Corresponde a la ruta en la cual se encuentra el
     *                   archivo en que se va a escribir el evento log.
     * 
     * @throws Exception Excepción genérica capturada en caso de ocurrir algún 
     *                   problema en la escritura al archivo de registro.
     */
    public void writeIntoFile(String strArchivo) throws Exception {
        FileWriter fichero = null;
        //PrintWriter pw; // = null;
        String strMensaje = "";
        switch (this.__CODE_TYPE_STR_LOG) {
            case 1:
                strMensaje = "[" + this.__TYPE + "][" + this.__TIME + "] " + this.__MENSAJE;
                break;
            case 2:
                strMensaje = "[" + this.__TYPE + "][" + this.__TIME + "][" + this.__METHOD + "] " + this.__MENSAJE;
                break;
            case 3:
                strMensaje = "[" + this.__TYPE + "][" + this.__TIME + "][" + this.__METHOD + "][" + this.__USUARIO + "] " + this.__MENSAJE;
                break;
            case 4:
                strMensaje = "[" + this.__TYPE + "][" + this.__TIME + "][" + this.__METHOD + "][" + this.__USUARIO + "][" + this.__AMBIENTE + "] " + this.__MENSAJE;
                break;
        }

        try {
            fichero = new FileWriter(strArchivo, true);
            PrintWriter pw = new PrintWriter(fichero);
            pw.println(strMensaje);
        } catch (Exception ex) {
            String strError = "Ha ocurrido un error al intentar escribir en " + strArchivo + '\n';
            throw (new Exception(strError + ex.getMessage(), ex));
        } finally {
            try {
                if (null != fichero) {
                    fichero.close();
                }
            } catch (Exception ex) {
                String strError = "Imposible cerrar el archivo " + strArchivo;
                throw (new Exception(strError + ex.getMessage(), ex));
            }
        }
    } /* FIN public void writeIntoFile */

    /**
     * 
     * Método que tiene como tarea escribir el registro del evento log en una
     * base de datos.
     * 
     * @throws Exception Excepción genériga capturada si existe algún problema
     *                   al escribir en la base de datos.
     */
    public void writeIntoBD(int __ID_APLICACION) throws Exception {
        String strSQL = "";
        this.__ID_APLICACION = __ID_APLICACION;

        switch (this.__CODE_TYPE_STR_LOG) {
            case 1:
                strSQL = "INSERT INTO log_mstr"
                        + "(log_apl_codigo, log_tipo, log_instante, log_fecha_hora, log_detalle) "
                        + "VALUES ("
                        + this.__ID_APLICACION + ", '"
                        + this.__TYPE + "', "
                        + this.__LONG_TIME + ", '"
                        + this.__SQL_TIME + "', '"
                        + this.__MENSAJE + "')";
                break;
            case 2:
                strSQL = "INSERT INTO log_mstr"
                        + "(log_apl_codigo, log_tipo, log_instante, log_fecha_hora, log_detalle, log_metodo) "
                        + "VALUES ("
                        + this.__ID_APLICACION + ", '"
                        + this.__TYPE + "', "
                        + this.__LONG_TIME + ", '"
                        + this.__SQL_TIME + "', '"
                        + this.__MENSAJE + "', '"
                        + this.__METHOD + "')";
                break;
            case 3:
                strSQL = "INSERT INTO log_mstr"
                        + "(log_apl_codigo, log_tipo, log_instante, log_fecha_hora, log_detalle, log_metodo, log_usuario) "
                        + "VALUES ("
                        + this.__ID_APLICACION + ", '"
                        + this.__TYPE + "', "
                        + this.__LONG_TIME + ", '"
                        + this.__SQL_TIME + "', '"
                        + this.__MENSAJE + "', '"
                        + this.__METHOD + "', '"
                        + this.__USUARIO + "')";
                break;
            case 4:
                strSQL = "INSERT INTO log_mstr"
                        + "(log_apl_codigo, log_tipo, log_instante, log_fecha_hora, log_detalle, log_metodo, log_usuario, log_ambiente) "
                        + "VALUES ("
                        + this.__ID_APLICACION + ", '"
                        + this.__TYPE + "', "
                        + this.__LONG_TIME + ", '"
                        + this.__SQL_TIME + "', '"
                        + this.__MENSAJE + "', '"
                        + this.__METHOD + "', '"
                        + this.__USUARIO + "', '"
                        + this.__AMBIENTE + "')";
                break;
        }
        if (!"".equals(strSQL)) {
            try {
                classMySQL MySQL = new classMySQL(this.__PROPERTIE_URL);
                MySQL.ordenSQL(strSQL);
            } catch (Exception ex) {
                String strError = "Error al ejecutar SQL: " + strSQL;
                throw (new Exception(strError + ex.getMessage(), ex));
            }
        }

    }

    /*********************************************************************/
    /***                       MÉTODOS PRIVADOS                        ***/
    /*********************************************************************/
    /**
     * 
     * Método de SET del objeto mensaje.
     * Corresponde al SET básico el cual sólo recibe como parámetro el tipo y 
     * el mensaje. Este método de manera interna realiza la captura del
     * instante en que se generó el evento log y lo registra para manejo futuro.
     * 
     * @param __STR_TYPE Define el tipo de mensaje que se registrará en el log.
     * @param __STR_MENSAJE Define el mensaje que será registrado en el log.
     * 
     */
    private void setObjClassMensaje(
            String __STR_TYPE,
            String __STR_MENSAJE) {
        this.__INSTANTE = this.getInstante();
        this.__TIME = this.getTime(this.__INSTANTE);
        this.__SQL_TIME = this.getSQLTime(this.__INSTANTE);
        this.__LONG_TIME = this.getLongTime(this.__INSTANTE);

        this.__TYPE = __STR_TYPE;
        this.__MENSAJE = __STR_MENSAJE;
    }   /* FIN private void setObjClassMensaje */


    /**
     * 
     * Método de SET del objeto mensaje.
     * Este método, de manera interna, invoca al método SET básico del objeto
     * mensaje.
     * 
     * @param __STR_TYPE Define el tipo de mensaje que se registrará en el log
     * @param __STR_MENSAJE Define el mensaje que será registrado en el log.
     * @param __METHOD Define el método al cual se asocia el evento de log.
     */
    private void setObjClassMensaje(
            String __STR_TYPE,
            String __STR_MENSAJE,
            String __METHOD) {
        this.__METHOD = __METHOD;
        setObjClassMensaje(__STR_TYPE, __STR_MENSAJE);
    } /* FIN private void setObjClassMensaje */


    /**
     * 
     * Método de SET del objeto mensaje.
     * Este método, de manera interna, invoca al método SET básico del objeto
     * mensaje.
     * 
     * @param __STR_TYPE Define el tipo de mensaje que se registrará en el log
     * @param __STR_MENSAJE Define el mensaje que será registrado en el log.
     * @param __METHOD Define el método al cual se asocia el evento de log.
     * @param __USUARIO Define el usuario generador del evento log (es útil 
     *                  para el control de sistemas multiusuarios).
     */
    private void setObjClassMensaje(
            String __STR_TYPE,
            String __STR_MENSAJE,
            String __METHOD,
            String __USUARIO) {
        this.__USUARIO = __USUARIO;
        setObjClassMensaje(__STR_TYPE, __STR_MENSAJE, __METHOD);
    } /* FIN private void setObjClassMensaje */


    /**
     * 
     * Método de SET del objeto mensaje.
     * Este método, de manera interna, invoca al método SET básico del objeto
     * mensaje.
     * 
     * @param __STR_TYPE Define el tipo de mensaje que se registrará en el log
     * @param __STR_MENSAJE Define el mensaje que será registrado en el log.
     * @param __METHOD Define el método al cual se asocia el evento de log.
     * @param __USUARIO Define el usuario generador del evento log (es útil 
     *                  para el control de sistemas multiusuarios).
     * @param __AMBIENTE Define el ambiente en que es generado el evento log 
     *                   (es útil para implementaciones de sistemas 
     *                   multiambiente).
     */
    private void setObjClassMensaje(
            String __STR_TYPE,
            String __STR_MENSAJE,
            String __METHOD,
            String __USUARIO,
            String __AMBIENTE) {
        this.__AMBIENTE = __AMBIENTE;
        setObjClassMensaje(__STR_TYPE, __STR_MENSAJE, __METHOD, __USUARIO);
    } /* FIN private void setObjClassMensaje */


    /**
     * 
     * Método que registra y retorna el instante en que es invocado. Su objetivo
     * es ser utilizado para almacenar el instante de generación de un evento
     * log.
     * 
     * @return Un objeto tipo Timestamp creado en el instante en que
     *         <code>getInstante()</code> es invocado.
     */
    private Timestamp getInstante() {
        Date utilDate = new Date();
        return (new Timestamp(utilDate.getTime()));
    } /* FIN private Timestamp getInstante */


    /**
     * 
     * Método que obtiene la fecha desde <code>Timestamp instante</code>, le 
     * aplica el formado <code>yyyy-MM-dd HH:mm:ss.SSS</code> y la retorna como
     * <code>String</code>.
     * Se puede apreciar que "<code>SSS</code>" representa los milisegundos
     * contenidos en el instante.
     * 
     * @param instante Corresponde al instante del cual se obtendrá la fecha
     *                 a formatear.
     * 
     * @return La fecha obtenida de <code>Timestamp instante</code> en un 
     *         <code>String</code> con formato "<code>yyyy-MM-dd HH:mm:ss.SSS</code>".
     */
    private String getTime(Timestamp instante) {
        SimpleDateFormat formatoFechaHora = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
        return formatoFechaHora.format(instante);
    } /* FIN private String getTime */


    /**
     * 
     * Método que obtiene la fecha desde <code>Timestamp instante</code>, le 
     * aplica el formado <code>yyyy-MM-dd HH:mm:ss</code> y la retorna como
     * <code>String</code>.
     * 
     * @param instante Corresponde al instante del cual se obtendrá la fecha
     *                 a formatear.
     * 
     * @return La fecha obtenida de <code>Timestamp instante</code> en un 
     *         <code>String</code> con formato "<code>yyyy-MM-dd HH:mm:ss</code>".
     */
    private String getSQLTime(Timestamp instante) {
        SimpleDateFormat formatoFechaHora = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return formatoFechaHora.format(instante);
    } /* FIN private String getSQLTime */


    /**
     * 
     * Método que obtiene la fecha desde <code>Timestamp instante</code>, pero 
     * no le aplica formato, retornando su valor como un <code>long</code>
     * 
     * @param instante Corresponde al instante del cual se obtendrá la fecha
     *                 a formatear.
     * 
     * @return La fecha obtenida de <code>Timestamp instante</code> en formato 
     *         <code>long</code>.
     */
    private long getLongTime(Timestamp instante) {
        return instante.getTime();
    } /* private long getLongTime */

}   